//////////////////////////////////////////////
// String.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Forward decl -----------------------------

namespace nkLog
{
	class StringView ;
}

/// Includes ---------------------------------

// nkLog
#include "../Dll/DllDefines.h"

// Standards
#include <string>
#include <string_view>

/// Class ------------------------------------

namespace nkLog
{
	class DLL_LOG_EXPORT String final
	{
		public :

			// Functions
			// Constructor, destructor
			String () noexcept ;
			String (char c) noexcept ;
			String (const char* data) noexcept ;
			String (unsigned long long size) noexcept ;
			String (const char* data, unsigned long long size) noexcept ;
			String (const String& other) noexcept ;
			String (String&& other) noexcept ;
			~String () ;

			// Getters
			char* getData () const ;
			unsigned long long getSize () const ;

			// Operators
			char operator[] (unsigned long long index) const ;
			char& operator[] (unsigned long long index) ;
			String& operator= (const StringView& other) ;
			String& operator= (String&& other) ;
			String operator+ (char c) const ;
			String operator+ (const StringView& other) const ;
			void operator+= (char c) ;
			void operator+= (const StringView& other) ;

		public :

			// Inlined constructors
			template <typename T = std::string>
			String (const std::string& str) noexcept
			:	_data (nullptr),
				_size ((unsigned long long)str.size())
			{
				// Copy data over
				_data = new char [_size + 1] ;
				memcpy(_data, str.data(), _size) ;
				_data[_size] = '\0' ;
			}

			template <typename T = std::string_view>
			String (const std::string_view& str) noexcept
			:	_data (nullptr),
				_size ((unsigned long long)str.size())
			{
				// Copy data over
				_data = new char [_size + 1] ;
				memcpy(_data, str.data(), _size) ;
				_data[_size] = '\0' ;
			}

		public :

			// Inlined conversions
			template <typename T = std::string>
			operator std::string () const
			{
				return std::string(_data, _size) ;
			}

			template <typename T = std::string_view>
			operator std::string_view () const
			{
				return std::string_view(_data, _size) ;
			}

		private :

			// Attributes
			char* _data ;
			unsigned long long _size ;
	} ;

	inline nkLog::String operator+ (char c, const nkLog::String& str)
	{
		nkLog::String result (str.getSize() + 1) ;

		result.getData()[0] = c ;
		memcpy(&result.getData()[1], str.getData(), str.getSize()) ;

		return result ;
	}

	inline nkLog::String operator+ (const char* c, const nkLog::String& str)
	{
		size_t otherLength = strlen(c) ;
		nkLog::String result (str.getSize() + otherLength) ;

		memcpy(result.getData(), c, otherLength) ;
		memcpy(&result.getData()[otherLength], str.getData(), str.getSize()) ;

		return result ;
	}
}